package com.zjpavt.client.hal.network;

import com.zjpavt.client.hal.RouteDefaultController;
import com.zjpavt.client.nativemethod.JnIMethod;
import com.zjpavt.client.util.ClientConfig;
import com.zjpavt.client.util.LoggerUtil;
import com.zjpavt.client.util.ProcessUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.File;

/**
 * 插入4g模块 TTY_USB_0_FLIE.isExist
 * 插入4g模块没有信号强度  没有插入sim卡
 * 重启4g模块成功 无标志 todo
 * 没有拨号成功上网 无法获取到ppp0的ip
 * @author zyc
 */
@Slf4j
public class WirelessNetwork extends AbstractNetwork {
    /**
     * 重新尝试连接GPRS次数
     */
    private static int retryCallGprs = 0;
    /**
     * 最大重连次数
     */
    private static final int MAX_RETRY_CALL_GPRS = 3;
    /**
     * 重启4G模块次数 都是单线程使用没有并发问题
     */
    private static int tryReconnect4G = 0;
    /**
     * 最大重连次数
     * 例如为1 则失败后会重试一次
     */
    private static final int MAX_RECONNECT_4G = 1;
    /**
     * 4g模块的重连脚本
     */
    private static final String RECONNECT_SHELL = "sh " + ClientConfig._4G_SHELL_PATH + " restart";
    /**
     * 4G模块是否插入标志位  文件是否存在
     */
    public static final File TTY_USB_0_FLIE = new File("/dev/ttyUSB0");
    public static final String _4G_WITHOUT_SIGNAL = "-1";



    public WirelessNetwork(String name) {
        setName(name);
        setType(NetworkManager.NETWORK_4G);
    }

    @Override
    public boolean isWithIp() {
        return this.interfaceAddress != null;
    }

    /**
     * 设置本连接为默认路由
     * @return
     */
    @Override
    public boolean usdAsDefault() {
        if (isWithIp()) {
            RouteDefaultController.getINSTANCE().changeDefaultRoute(RouteDefaultController.Route.PPP0);
//            NetworkManager.getInstance().get
            return true;
        } else {
            if (WirelessNetwork.tryConnect4G()) {
                NetworkManager.getInstance().refreshNetworkStatus();
//                重启后是否处于活跃状态
                if (isWithIp()) {
                    RouteDefaultController.getINSTANCE().changeDefaultRoute(RouteDefaultController.Route.PPP0);
                    return true;
                } else {
                    log.error("network"+"connect is not Active fail-----------------------------------------");
                    return false;
                }
            } else {
                log.error("network"+"connect 4G fail-----------------------------------------");
                return false;
            }
        }
    }

    /**
     * 重连模块：相当于重新调用本地配置，尝试重新连接到运营商  前置条件--模块正常()，异常时可尝试重启模块
     * 重启模块：硬件重启，当重连多次无效以后
     *
     * 尝试重启4G模块
     *
     * 修改回路状态到4G
     * 最终是为了确保PPP0 启动
     *
     * ppp0可能没有启动 判断标志为/run/ppp0.pid是否存在
     * 如果已经存在 直接调用RouteDefaultController切换默认路由
     * 如果不存在则尝试调用4G脚本 尝试重新连接 并记录tryReconnect4G次数 并等待35S 尝试次数为MAX_RETRY_CALL_GPRS（3）
     *
     * 当Gprs次数超过阈值的时候，尝试重启4G模块 并记录尝试次数 如果已经尝试过 则认为本次切换到4G模块失败，
     * 且将路由切换到AUTO（目前的AUTO处理同切换到以太网 NETWORK_ENTE）
     * @return  是否能连接到4G模块
     */
    public static synchronized boolean tryConnect4G() {
        if (!is4GModalExist()) {
            log.error("network"+"4G module isn't exists in device!change to 4G fail.");
            return false;
        }
//      先尝试重连一次 如果不成功则重启4G模块
        if (reconnect4GModule(3,120)) {
            log.info("network reconnect 4G success");
            return true;
        } else {
            log.error("network 4g module is not ready. try to restart 4G moudle");
            JnIMethod.restart4G();
            /* if (reconnect4GModule(2,15)) {
                 log.info("network"+"reconnect 4G success");
                 return true;
             } else {
                 log.error("network"+"after restart 4G,connect fail!!!");
                 return false;
             }*/
        }
        return false;
    }

    public static boolean is4GModalExist() {
        if (TTY_USB_0_FLIE.exists()) {
            return true;
        }
        return false;
    }

    /**
     * @param connectOverTime 单次重连超时时间
     * @param reconnectTimes 尝试重连次数
     * @return 尝试重连是否成功
     */
    private static boolean reconnect4GModule(int reconnectTimes, int connectOverTime) {
        log.info("network"+"tryConnect4G");
        tryReconnect4G = 0;
        long startTime = System.currentTimeMillis();
//        重新拨号次数
        while (tryReconnect4G++ < reconnectTimes) {
            if (NetworkManager.getInstance().refreshNetworkStatus().containNetwork(NetworkManager.INTERFACE_PPP_0)) {
                return true;
            } else {
                new Thread(()-> {
                    JnIMethod._4G_Lock.lock();
                    try {
                        ProcessUtil.execWithLog(RECONNECT_SHELL);
                    }
                    finally {
                        JnIMethod._4G_Lock.unlock();
                    }
                }).start();
                try {
                    int time = 0;
                    while (time < connectOverTime) {
                        time++;
                        Thread.sleep(1000);
                        if (NetworkManager.getInstance().refreshNetworkStatus().containNetwork(NetworkManager.INTERFACE_PPP_0)) {
                            log.info("network"+"reconnect4GModule success used time " + time + " second");
                            return true;
                        } else {
                            log.error("network"+"reconnect4GModule fail used time " + time + " second");
                        }
                    }
                } catch (InterruptedException e) {
                    log.error("network"+LoggerUtil.convertException2String(e));
                }
//              尝试重启sh脚本后是否启动成功
            }
            log.info("network reconnect fail have try" + tryReconnect4G + "times. reconnectTimes =" + reconnectTimes);
        }
        if (NetworkManager.getInstance().refreshNetworkStatus().containNetwork(NetworkManager.INTERFACE_PPP_0)) {
            log.info("network"+"reconnect4GModule success reconnectTimes="+ reconnectTimes + " connectOverTime=" + connectOverTime+" success!");
            return true;
        }
        log.error("network reconnect4GModule reconnectTimes="+ reconnectTimes + " connectOverTime=" + connectOverTime+" fail！");
        return false;
    }


}
